/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package choreganizer;


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;



public class MyGlassPane extends JComponent implements MouseListener
{

    private Thread	    animation;
    private String	    text;
    private String	    textHolder;
    private RenderingHints  rendHints;
    private int		    alphaLevel;
    private int		    ticks = 3;
    private int		    currentTick;
    private boolean	    fadeIn;
    private boolean	    fadeOut;
    private boolean	    keepAlive;
    private TextLayout	    maxLayout;
    private long	    minimumRunTime;


    public MyGlassPane()
    {
	this("");
    }


    public MyGlassPane(String text)
    {
	text.trim();
	textHolder = text;	// Put the actual text in a placeholder till we've faded in
	this.text = null;		// Set text to null for now
	rendHints = new RenderingHints(RenderingHints.KEY_RENDERING, 
		RenderingHints.VALUE_RENDER_QUALITY);
	rendHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
	rendHints.put(RenderingHints.KEY_FRACTIONALMETRICS, 
		RenderingHints.VALUE_FRACTIONALMETRICS_ON);

	alphaLevel = 0;
	setOpaque(false);
    }

    /*
     * Treat visibility changes as accessor methods to starting/stopping
     * our 
     */
    @Override
    public void setVisible(boolean visible)
    {
	if (visible)
	    this.start();
	else
	    this.stop();
    }
    
    
    /*
    * This will gracefully insert the glass pane,
    * fading the program out
    */
    public void start()
    {
	minimumRunTime = System.currentTimeMillis() + 2000;
	alphaLevel = 0;
	currentTick = 0;
	keepAlive = true;
	fadeIn = true;
	addMouseListener(this);
	super.setVisible(true);
	animation = new Thread(new Animator());
	animation.start();
    }



    /*
    * This will gracefully remove the glass pane, 
    * fading the program back in
    */
    public void stop()
    {
	if (animation != null) 
	{
	    fadeOut = true;
	    animation = null;
	}
    }


    /*
    * This will immediately get rid of the glass pane
    */
    public void interrupt()
    {
	if (animation != null) 
	{
	    animation.interrupt();
	    animation = null;

	    removeMouseListener(this);
	    setVisible(false);
	    repaint();
	}
    }


    @Override
    public void paintComponent(Graphics g)
    {
	int width  = getWidth();
	int height = getHeight();

	// Set the rendering hints
	Graphics2D g2 = (Graphics2D)g;
	g2.setRenderingHints(rendHints);

	// Set the alpha level
	g2.setColor(new Color(255, 255, 255, alphaLevel));
	g2.fillRect(0, 0, getWidth(), getHeight());

	// Draw the text to the screen
	if (text != null)
	{
	    Font lFont = new Font( getFont().getName(), Font.BOLD, 30 );
	    FontRenderContext context = g2.getFontRenderContext();

	    // Determine the size along w/ the periods
	    /*if (maxLayout == null)
	    {
		StringBuilder sb = new StringBuilder();
		sb.append(text);
		for (int i=0; i<ticks; i++)
		    sb.append(".");

		maxLayout = new TextLayout(sb.toString(), lFont, context);
	    }

	    String tmpText = text;
	    currentTick++;
	    if (currentTick > ticks)
		currentTick = 0;

	    for (int i=0; i < currentTick; i++)
		tmpText += ".";*/
		maxLayout = new TextLayout(text.toString(), lFont, context);
		String tmpText = text;
	    TextLayout layout = new TextLayout(tmpText, lFont, context);
	    Rectangle2D bounds = maxLayout.getBounds();
	    g2.setColor(getForeground());

	    // Center drawn text
	    layout.draw(
		g2, 
		(float)(width-bounds.getWidth())/2, 
		(float)(height-bounds.getHeight())/2
	    );
	}
    }



    private boolean threadStopCheck()
    {
	if (!keepAlive && System.currentTimeMillis() >= minimumRunTime && !fadeOut && !fadeIn)
	    return false;
	else
	    return true;
    }

    protected class Animator implements Runnable
    {
	@Override
	public void run()
	{
	    // First we'll create a fade-in by increasing the alpha
	    // Then we'll continuously loop a small animation
	    // When the program wants to stop, we'll be used to fade-out
	    while (!Thread.interrupted() && threadStopCheck())
	    {
		if (fadeIn)
		{
		    if (alphaLevel < 140)
			alphaLevel += 5;
		    else
		    {
			fadeIn = false;
			text = textHolder;
		    }
		}

		if (fadeOut && System.currentTimeMillis() >= minimumRunTime)
		{
		    if (text != null)
			text = null;
		    if (alphaLevel > 0)
			alphaLevel -= 5;
		    else
		    {
			fadeOut = false;
			keepAlive = false;
		    }
		}

		// Call repaint to enact any animations
		repaint();

		// Control the animation framerate
		try {
		    if (fadeIn || (fadeOut && System.currentTimeMillis() >= minimumRunTime))
			Thread.sleep(5);
		    else
			Thread.sleep(180);
		} catch (InterruptedException ie) {
		    MyGlassPane.super.setVisible(false);
		    removeMouseListener(MyGlassPane.this);
		    repaint();
		    break;
		}

		// Check if any other threads need to work
		Thread.yield();
	    }

	    // Thread is stopping, cleanup
	    MyGlassPane.super.setVisible(false);
	    removeMouseListener(MyGlassPane.this);
	    repaint();
	}

    }



    /*
    * We implement the mouse listeners simply to intercept
    * events, and to keep them from bubbling down
    */
    @Override
    public void mouseClicked(MouseEvent e){}
    @Override
    public void mousePressed(MouseEvent e){}
    @Override
    public void mouseReleased(MouseEvent e){}
    @Override
    public void mouseEntered(MouseEvent e){}
    @Override
    public void mouseExited(MouseEvent e){}
}
